Skip to content

Use two-tier CA signing for browser-trustable certificates#39

Merged
ryoluo merged 1 commit intomainfrom
devin/1771669409-two-tier-ca-cert
Feb 21, 2026
Merged

Use two-tier CA signing for browser-trustable certificates#39
ryoluo merged 1 commit intomainfrom
devin/1771669409-two-tier-ca-cert

Conversation

@devin-ai-integration
Copy link
Contributor

Use two-tier CA signing for browser-trustable certificates

Summary

Replaces the single self-signed certificate with a proper Root CA → Server Certificate chain. This resolves #28 where Firefox rejects the generated certificate with MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY because the old self-signed cert had basicConstraints = CA:TRUE by default.

generate-ssl-cert.sh now:

  1. Generates a Root CA keypair (root-ca.key / root-ca.crt)
  2. Generates a server CSR, then signs it with the Root CA
  3. Sets basicConstraints=CA:FALSE, keyUsage, extendedKeyUsage=serverAuth on the server cert
  4. Preserves the SSL_ALT_NAME empty-value guard from Fix certificate generation failure when SSL_ALT_NAME is empty #38
  5. Cleans up temporary files (CSR, ext config, serial)

README.md adds instructions for importing the Root CA into Chrome, Firefox, and macOS Keychain so users can eliminate browser security warnings entirely.

server.key / server.pem paths are unchanged, so no changes to the nginx config are needed.

Review & Testing Checklist for Human

  • Docker end-to-end test: Run sail up with a fresh environment (delete sail-nginx volume first) and confirm nginx starts without errors and both root-ca.crt and server.pem are generated in /etc/nginx/certs/
  • Firefox verification: Import root-ca.crt into Firefox and confirm MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY no longer occurs
  • Chrome verification: Import root-ca.crt and confirm the connection is trusted
  • Inspect the generated cert: Run openssl x509 -in server.pem -text -noout inside the nginx container and verify CA:FALSE, keyUsage, extendedKeyUsage, and subjectAltName are set correctly
  • Test without SSL_ALT_NAME: Remove or empty SSL_ALT_NAME from docker-compose and confirm cert generation still succeeds (SAN line omitted from ext file)
  • Existing volume upgrade path: Confirm that users with an existing sail-nginx volume see the "already exists" message and must delete the volume to regenerate

Notes

  • CI only covers PHP unit tests — the shell script has no automated test coverage and must be verified manually in Docker
  • The 3650-day validity on the server cert exceeds Apple's 398-day limit for publicly trusted certs. This is pre-existing and out of scope here, but worth considering in a follow-up.
  • This is a breaking change for existing users in the sense that they must delete their sail-nginx Docker volume to get the new two-tier certs. This is documented in the README.
  • Requested by: @ryoluo
  • Link to Devin run: https://app.devin.ai/sessions/34d95668212e4f198ed7fef19e05591c

Co-Authored-By: Ryo Kobayashi <cuba6vst@gmail.com>
@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@ryoluo ryoluo merged commit 5e5a66f into main Feb 21, 2026
5 checks passed
@ryoluo ryoluo deleted the devin/1771669409-two-tier-ca-cert branch February 21, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to add generated certificate to Firefox as trusted CA

1 participant